﻿using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE;
using EnvDTE80;

namespace dFactor2.CodeHelpers
{
    public class Properties : CodeHelperBase
    {
        public Properties(DTE2 applicationObject) : base(applicationObject) { }

        public void EncapsulateField(bool addChangeNotification)
        {
            CodeVariable codeVar = GetCurrentCodeElement<CodeVariable>(vsCMElement.vsCMElementVariable);
            if (codeVar == null)
            {
                return;
            }

            string Name = codeVar.Name;

            codeVar.Name = "_" + Name;
            codeVar.Access = vsCMAccess.vsCMAccessPrivate;

            CodeProperty codeProp = ((CodeClass)codeVar.Parent).AddProperty(Name, Name, codeVar.Type.AsFullName, codeVar, vsCMAccess.vsCMAccessPublic, null);

            EditPoint edtpnt = codeProp.GetStartPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
            edtpnt.Delete(codeProp.Getter.EndPoint.CreateEditPoint());
            edtpnt.Delete(codeProp.Setter.EndPoint.CreateEditPoint());

            edtpnt.Insert("\nget { return _" + Name + "; }");

            if (addChangeNotification)
            {
                edtpnt.Insert("\nset { _" + Name + " = value; OnPropertyChanged(\"" + Name + "\"); }");
            }
            else
            {
                edtpnt.Insert("\nset { _" + Name + " = value; }");
            }

            edtpnt.SmartFormat(codeProp.StartPoint);
            edtpnt.SmartFormat(codeProp.EndPoint);
        }

        public void AddBacking(bool addChangeNotification)
        {
            CodeProperty codeProp = GetCurrentCodeElement<CodeProperty>(vsCMElement.vsCMElementProperty);
            if (codeProp == null)
            {
                return;
            }

            CodeClass cpParentClass = codeProp.Parent as CodeClass;

            cpParentClass.AddVariable("_" + codeProp.Name, codeProp.Type.AsFullName, codeProp, vsCMAccess.vsCMAccessPrivate, null);

            string propName = codeProp.Name;
            EditPoint edtpnt = codeProp.GetStartPoint(vsCMPart.vsCMPartBody).CreateEditPoint();

            edtpnt.Delete(codeProp.Getter.EndPoint.CreateEditPoint());
            edtpnt.Delete(codeProp.Setter.EndPoint.CreateEditPoint());

            edtpnt.Insert("\nget { return _" + propName + "; }");

            if (addChangeNotification)
            {
                edtpnt.Insert("\nset { _" + propName + " = value; OnPropertyChanged(\"" + propName + "\"); }");
            }
            else
            {
                edtpnt.Insert("\nset { _" + propName + " = value; }");
            }

            edtpnt.SmartFormat(codeProp.StartPoint);
            edtpnt.SmartFormat(codeProp.EndPoint);
        }

        public void ConvertVariableToProperty()
        {
            CodeVariable codeVar = GetCurrentCodeElement<CodeVariable>(vsCMElement.vsCMElementVariable);
            if (codeVar == null)
            {
                return;
            }

            string Name = codeVar.Name;

            codeVar.Name = "_" + Name;
            codeVar.Access = vsCMAccess.vsCMAccessPrivate;

            CodeProperty codeProp = ((CodeClass)codeVar.Parent).AddProperty(Name, Name, codeVar.Type.AsFullName, codeVar, codeVar.Access, null);
            ((CodeClass)codeVar.Parent).RemoveMember(codeVar);

            EditPoint edtpntp = codeProp.GetStartPoint(vsCMPart.vsCMPartBody).CreateEditPoint();
            edtpntp.Delete(codeProp.Getter.EndPoint.CreateEditPoint());
            edtpntp.Delete(codeProp.Setter.EndPoint.CreateEditPoint());

            edtpntp.Insert("get; set;");

        }

        public void IncludeChangeNotification()
        {
            CodeProperty codeProp = GetCurrentCodeElement<CodeProperty>(vsCMElement.vsCMElementProperty);
            if (codeProp == null)
            {
                return;
            }

            EditPoint edtpnt = codeProp.Setter.GetEndPoint(vsCMPart.vsCMPartBody).CreateEditPoint();

            edtpnt.Insert(" OnPropertyChanged(\"" + codeProp.Name + "\"); ");
        }
    }
}
